﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using config = PeoplesJukebox.Core.Configuration;
using PeoplesJukebox.Core.Interfaces;
using PeoplesJukebox.Core.MediaItems;
using PeoplesJukebox.Core.Logging;
using PeoplesJukebox.Core.MediaItems.Bases;
using PeoplesJukebox.Core.Enums;

namespace PeoplesJukebox.Core.TrackLists.Bases
{
    /// <summary>
    /// Base class for tracklists
    /// </summary>
    public abstract class TrackListBase : ITrackList
    {
        #region Protected static members

        /// <summary>
        /// Gets/sets the list of tracks which have been played
        /// </summary>
        protected static List<int> PlayedTracks { get; set; }

        #endregion

        #region Abstract members

        /// <summary>
        /// Returns whether the tracklist has more tracks to play 
        /// </summary>
        public abstract bool HasTracks{ get; }

        /// <summary>
        /// Gets the name of the tracklist
        /// </summary>
        public abstract string Name { get; }

        /// <summary>
        /// Returns the ID of the next track in the list
        /// </summary>
        /// <returns>Track ID</returns>
        protected abstract int GetNextTrackId();

        #endregion

        #region Public instance members

        /// <summary>
        /// Gets/sets the "chosen by" text for the tracklist
        /// </summary>
        public string ChosenByText { get; set; }
        
        /// <summary>
        /// Returns whether the traklist allows a played track to be repeated
        /// </summary>
        public virtual bool AllowsRepeatPlay
        {
            get { return false; }
        }

        /// <summary>
        /// Gets the next track in the list
        /// </summary>
        /// <returns>Track</returns>
        public Track GetNextTrack()
        {
            Log.Info("{0}: GetNextTrack called", this.Name);
            Track track = null;
            if (this.HasTracks)
            {
                int trackId = this.GetNextTrackId();
                while (PlayedTracks.Contains(trackId) && !this.AllowsRepeatPlay)
                {
                    if (this.HasTracks)
                    {
                        trackId = this.GetNextTrackId();
                        Log.Info("{0}: GetNextTrack returned trackId {1}", this.Name, trackId);
                    }
                    else
                    {
                        trackId = -1;
                        break;
                    }
                }
                if (trackId > -1)
                {
                    track = Container.Catalogue.GetTrack(trackId);
                    if (track != null)
                    {
                        Log.Info("{0} chose: {1}", this.Name, track.Name);
                        PlayedTracks.Add(trackId);
                    }
                }
            }
            return track;
        }

        /// <summary>
        /// Loads the tracklist
        /// </summary>
        public virtual void Load()
        {
            PlayedTracks = new List<int>();
        }

        #endregion

        #region Protected instance methods

        /// <summary>
        /// Gets the ID of the configured track with the given index
        /// </summary>
        /// <param name="configuredCollection">Configured track collection</param>
        /// <param name="trackIndex">Index of track</param>
        /// <returns>Track ID</returns>
        protected int GetConfiguredTrackId(config.TrackCollection configuredCollection, int trackIndex)
        {
            int trackId = -1; 
            config.Track nextTrack = configuredCollection.GetConfiguredTrack(trackIndex);
            if (nextTrack != null)
            {
                List<MediaItem> tracks = Container.Catalogue.Search(nextTrack.TrackName, MediaItemType.Track);
                if (tracks.Count == 1 && tracks[0] is Track)
                {
                    trackId = tracks[0].Id;
                }
                else if (tracks.Count > 1)
                {
                    //if there's more than one match, pick the exact one:
                    foreach (MediaItem item in tracks)
                    {
                        if (item.Name.Length == nextTrack.TrackName.Length && item is Track)
                        {
                            trackId = item.Id;
                            break;
                        }
                    }
                }
            }
            return trackId;
        }

        #endregion
    }
}
